import React, { forwardRef, useImperativeHandle, useState } from 'react';

import { useRequest } from 'ahooks';
import { Button, Form, FormProps, Input, Modal, Radio, Select } from 'antd';

import Upload from '@/components/upload';

import { store } from '@/store';

import {
  emailValidator,
  mobileValidator,
  passwordValidator,
  userNameValidator
} from '@/config/rule';
import { TimeSort } from '@/enum';
import { UserStatus, UserStatusObj } from '@/enum/user';
import { securityPublicKey } from '@/services/base/denglumokuaidenglujiekou';
import { roleList as roleListApi } from '@/services/base/jiaoseguanlijiaosexiangguanjiekou';
import { orgUserInfoAdd, orgUserInfoUpdate } from '@/services/base/yonghuguanlixitongyonghujiekou';
import { parseSrc } from '@/utils';
import { encryptRSA } from '@/utils/encrypt';

import { BizObject } from '.';

type EditOpenBaseArgs = {
  /** 成功回调 */
  onSuccess?: () => void;
};

export type EditRef = {
  open: (
    arg:
      | (EditOpenBaseArgs & {
          type: 'add';
        })
      | (EditOpenBaseArgs & {
          type: 'edit';
          rowData: BizObject;
        })
      | (EditOpenBaseArgs & {
          type: 'detail';
          rowData: BizObject;
        })
  ) => void;
};

export type EditProps = {};

const Edit: React.ForwardRefRenderFunction<EditRef, EditProps> = ({ ...rest }, ref) => {
  const [form] = Form.useForm();
  const [open, setOpen] = useState(false);
  const [args, setArgs] = useState<ArgumentsType<EditRef['open']>[0]>();
  const roleList = useRequest(
    async () => {
      return (
        await roleListApi({
          timeSort: TimeSort.倒序
        })
      ).data;
    },
    {
      manual: true
    }
  );

  useImperativeHandle(ref, () => {
    return {
      open: (arg) => {
        setArgs(arg);
        setOpen(true);
        roleList.refresh();

        setTimeout(() => {
          if ((arg.type === 'edit' || arg.type === 'detail') && arg.rowData) {
            form.setFieldsValue({
              ...arg.rowData
            });
          } else {
            form.resetFields();
            // 回填数据
            form.setFieldsValue({
              state: UserStatus.正常
            });
          }
        });
      }
    };
  });

  const onFinish: FormProps['onFinish'] = async ({ password, _password, ...values }) => {
    const query = {
      ...values
    } as ArgumentsType<typeof orgUserInfoAdd | typeof orgUserInfoUpdate>[0];

    if (args?.type === 'edit' && args.rowData) {
      query.id = args.rowData.id;
    }

    // 加密
    if (password) {
      // 加密密码
      const publicKey = (await securityPublicKey()).data;
      const encryptedPassword = await encryptRSA(password, async () => publicKey);

      query.password = encryptedPassword;
    }

    await (args?.type === 'edit' ? orgUserInfoUpdate(query) : orgUserInfoAdd(query));

    args?.onSuccess?.();
    setOpen(false);
    store.app?.message.success(args?.type === 'edit' ? '编辑成功' : '新增成功');
  };

  const onClose = () => {
    form.resetFields();
    setOpen(false);
  };

  return (
    <Modal
      title={
        {
          add: '新增用户',
          edit: '编辑用户',
          detail: '用户详情'
        }[args?.type as string]
      }
      width={600}
      {...rest}
      open={open}
      onCancel={onClose}
      onOk={() => {
        form.submit();
      }}
    >
      <Form
        onFinish={onFinish}
        form={form}
        layout="horizontal"
        labelCol={{ span: 6 }}
        wrapperCol={{ span: 18 }}
      >
        <Form.Item
          name="username"
          label="用户名"
          rules={[
            {
              required: args?.type === 'add',
              message: '请输入用户名'
            },
            {
              validator: userNameValidator
            }
          ]}
        >
          <Input
            placeholder="用户名"
            allowClear
            disabled={args?.type === 'edit'}
            variant={args?.type === 'edit' || args?.type === 'detail' ? 'borderless' : undefined}
          />
        </Form.Item>

        <Form.Item
          label="真实姓名"
          name="fullName"
          rules={[
            {
              required: true,
              message: '请填写真实姓名'
            }
          ]}
        >
          <Input placeholder="真实姓名" />
        </Form.Item>

        <Form.Item noStyle shouldUpdate>
          {({ getFieldValue }) => {
            const photoUrl = getFieldValue('photoUrl');

            return (
              <Form.Item
                label="头像"
                name="photoUrl"
                extra={
                  photoUrl ? (
                    <Button
                      onClick={() => {
                        form.setFieldsValue({
                          photoUrl: ''
                        });
                      }}
                      size="small"
                      danger
                    >
                      删除
                    </Button>
                  ) : null
                }
              >
                <Upload accept="image/*" listType="picture-card" showUploadList={false}>
                  {photoUrl ? (
                    <img src={parseSrc(photoUrl)} alt="avatar" style={{ width: '100%' }} />
                  ) : (
                    <div>
                      <div style={{ marginTop: 8 }}>上传头像</div>
                    </div>
                  )}
                </Upload>
              </Form.Item>
            );
          }}
        </Form.Item>

        <Form.Item
          label="电话号码"
          name="phone"
          rules={[
            // { required: true, message: '请填写电话号码' },
            {
              validator: mobileValidator
            }
          ]}
        >
          <Input placeholder="电话号码" />
        </Form.Item>

        <Form.Item
          label="电子邮箱"
          name="email"
          rules={[
            // { required: true, message: '请填写电子邮箱' },
            {
              validator: emailValidator
            }
          ]}
        >
          <Input placeholder="电子邮箱" />
        </Form.Item>

        <Form.Item label="角色" name="roleIds">
          <Select
            mode="multiple"
            placeholder="请选择角色"
            options={roleList.data?.map((item) => {
              return {
                label: item.roleName,
                value: item.id
              };
            })}
          />
        </Form.Item>

        <Form.Item
          label="状态"
          name="state"
          rules={[
            {
              required: true,
              message: '请选择用户状态'
            }
          ]}
        >
          <Radio.Group>
            {Array.from(UserStatusObj).map((item) => {
              return (
                <Radio value={item[0]} key={item[0]}>
                  {item[1].text}
                </Radio>
              );
            })}
          </Radio.Group>
        </Form.Item>

        {/* 新增时需要输入密码 */}
        {args?.type === 'add' && (
          <>
            <Form.Item
              label="密码"
              name="password"
              rules={[
                {
                  required: true,
                  message: '请输入密码'
                },
                {
                  validator: passwordValidator
                }
              ]}
              hasFeedback
            >
              <Input.Password placeholder="密码" />
            </Form.Item>

            <Form.Item
              label="确认密码"
              name="_password"
              dependencies={['password']}
              rules={[
                {
                  required: true,
                  message: '请输入确认密码'
                },
                ({ getFieldValue }) => ({
                  validator(_, value) {
                    if (value && value !== getFieldValue('password')) {
                      return Promise.reject(new Error('两次输入的密码不一致!'));
                    }
                    return Promise.resolve();
                  }
                })
              ]}
              hasFeedback
            >
              <Input.Password placeholder="确认密码" />
            </Form.Item>
          </>
        )}
      </Form>
    </Modal>
  );
};

export default forwardRef(Edit);
